package com.xr.blackhoole.mvc.reflect;

import org.apache.commons.lang3.StringUtils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class WormholeReflectUtils {
    public static Class generateClass(String clazzName) {
        Class clazz = null;
        if (StringUtils.isNotEmpty(clazzName)) {
            try {
                clazz = Class.forName(clazzName);
            } catch (ClassNotFoundException e) {
            }
        }
        return clazz;
    }
    public static <T> T generateObject(String clazzName) {
        Class clazz = generateClass(clazzName);
        Object value = generateObject(clazz);
        return (T) value;
    }

    public static <T> T generateObject(Class clazz) {
        Object value = null;
        if (null != clazz) {
            try {
                value = clazz.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return (T) value;
    }

    /**
     * 自省设置属性值
     *
     * @param bean
     * @param property
     * @param params
     * @throws Exception
     */
    public static void setProperty(Object bean, String property, Object... params) {
        PropertyDescriptor propDesc = null;
        try {
            propDesc = new PropertyDescriptor(property, bean.getClass());
            if (null != propDesc) {
                Method methodSetUserName = propDesc.getWriteMethod();
                methodSetUserName.invoke(bean, params);
            }
        } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

    }

    public static void setProperty(Object bean, Object propertieBean) {
        List<String> propertyList = getPropertyList(propertieBean.getClass());
        if (null != propertyList && !propertyList.isEmpty()) {
            for (String propertyName : propertyList) {
                try {
                    Object value = getProperty(propertieBean, propertyName);
                    if(null!=value){
                        setProperty(bean, propertyName, value);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 自省获取属性值
     *
     * @param bean
     * @param property
     * @return
     * @throws Exception
     */
    public static Object getProperty(Object bean, String property) {
        try {
            PropertyDescriptor proDescriptor = new PropertyDescriptor(property, bean.getClass());
            if (null != proDescriptor) {
                Method methodGetUserName = proDescriptor.getReadMethod();
                return methodGetUserName.invoke(bean);
            }
        } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static PropertyDescriptor[] getPropertyDescriptorArray(Class clazz) {
        BeanInfo beanInfo = null;
        try {
            beanInfo = Introspector.getBeanInfo(clazz.getClass());
        } catch (IntrospectionException e) {
            e.printStackTrace();
        }
        if (null != beanInfo) {
            return beanInfo.getPropertyDescriptors();
        }
        return null;
    }

    /**
     * 获取属性列表
     *
     * @param clazz
     * @return
     */
    public static List<String> getPropertyList(Class clazz) {
        List<String> propertyList = new ArrayList<>();
        PropertyDescriptor[] propertyDescriptors = getPropertyDescriptorArray(clazz);
        if (null != propertyDescriptors && propertyDescriptors.length > 0) {
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                propertyList.add(propertyDescriptor.getName());
            }
        }

        return propertyList;
    }
}
